import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Shop } from './entities/shop.entity';
import { Repository } from 'typeorm';
import { CreateShopDto } from './dto/create-shop.dto';
import { PageQuery } from '../../../util/entity/page.entity';
import { buildQuery } from '../../../util/common-fn';
import { UpdateShopDto } from './dto/update-shop.dto';
import { UserItemService } from '../user-item/user-item.service';
import { UserItem } from '../user-item/entities/user-item.entity';
import { User } from '../../admin/user/entities/user.entity';
import { Money } from '../money/entities/money.entity';
import { RecordService } from '../record/record.service';
import { DictType } from '../../../util/enum/dict.enum';
import { DictSonService } from '../../admin/dict-son/dict-son.service';
import { FileService } from '../../common/file/file.service';

@Injectable()
export class ShopService {
  constructor(
    @InjectRepository(Shop)
    private shopRepository: Repository<Shop>,
    private userItemService: UserItemService,
    private recordService: RecordService,
    private dictSonService: DictSonService,
    private fileService: FileService,
  ) {}
  async create(createShopDto: CreateShopDto) {
    await this.shopRepository.save(createShopDto);
    await this.fileService.setUsed(createShopDto.imageUrl);
    return true;
  }

  findAll(pageQuery: PageQuery<Shop>) {
    return this.shopRepository.findAndCount(buildQuery(pageQuery));
  }

  findOne(id: number) {
    return this.shopRepository.findOneByOrFail({ id });
  }

  async update(id: number, updateShopDto: UpdateShopDto) {
    await this.shopRepository.update({ id }, updateShopDto);
    await this.fileService.setUsed(updateShopDto.imageUrl);
    return true;
  }

  remove(id: number) {
    return this.shopRepository.softDelete({ id });
  }

  /**
   * 购物 (交易)
   * @param id
   * @param userId
   */
  async buy(id: number, userId: number) {
    await this.shopRepository.manager
      .transaction(async (tr) => {
        // 获取购物信息用户信息
        const shop = await tr.findOneByOrFail(Shop, { id });
        const user = await tr.findOneOrFail(User, {
          where: { id: userId },
          relations: {
            moneys: true,
          },
        });
        // 找到用户付钱的类型,点券还是金币等等
        const userMoney = user.moneys.find(
          (item) => item.priceType === shop.priceType,
        );

        // 这是处理message
        const priceTypeName = await this.dictSonService.getNameByCode(
          DictType.DnfPriceType,
          shop.priceType,
        );
        const errorMessage = `花费${shop.price}${priceTypeName},得到${shop.name}`;
        // 如果用户的钱足够
        if (userMoney.num >= shop.price) {
          // 减去用户的钱
          await tr.decrement(Money, { id: userMoney.id }, 'num', shop.price);
          // 在用户的物品的找到这个物品,如果没有的话,就创建一个
          const userItem =
            await this.userItemService.findOrCreateOneByUserIdAndShop(
              userId,
              shop,
              tr,
            );
          // 将用户的物品数量增加
          await tr.increment(
            UserItem,
            { id: userItem.id },
            'itemNum',
            shop.itemNum,
          );
          return {
            errorMessage,
          };
        } else {
          // 钱不够
          throw new Error(`想要${errorMessage},但是钱不够啦.`);
        }
      })
      .then(async (result) => {
        await this.recordService.insertValues({
          user: { id: userId },
          success: 1,
          type: 1,
          errorMessage: result.errorMessage,
          shop: { id },
        });
      })
      .catch(async (err: Error) => {
        await this.recordService.insertValues({
          user: { id: userId },
          success: 0,
          type: 1,
          shop: { id },
          errorMessage: err.message,
        });
        throw new Error(err.message);
      });
  }
}
